package com.rybbaby.tss.tasks.core.web.service.imp;

import com.rybbaby.tss.tasks.core.bean.PageBean;
import com.rybbaby.tss.tasks.core.web.dao.imp.GenericDao;
import com.rybbaby.tss.tasks.core.web.service.IBaseService;
import org.apache.log4j.Logger;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.jdbc.core.SqlParameter;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.Column;
import javax.persistence.Id;
import javax.persistence.Table;
import java.io.Serializable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @description 基础Service接口实现
 *
 * @author 谢进伟
 *
 * @createDate 2016年2月3日 下午9:13:58
 */
@Transactional
public abstract class BaseServiceImp<T> extends GenericDao<T> implements IBaseService<T> {

	protected Class<T> cls;
	protected Logger log;

	public BaseServiceImp (){
		// 初始化时，自动设置泛型类
		this.setGenericType(0);
		log = Logger.getLogger(cls);
	}

	/**
	 * 打印调试日志信息
	 *
	 * @param message
	 *            调试信息
	 */
	protected void debug(String message) {
		if(log.isDebugEnabled()) {
			log.debug(message);
		}
	}

	/**
	 * 打印日志信息
	 *
	 * @param message
	 */
	protected void info(String message) {
		if(log.isInfoEnabled()) {
			log.info(message);
		}
	}

	/**
	 *
	 * 打印调试日志信息(包含异常信息)
	 *
	 * @param message
	 *            调试信息
	 * @param t
	 */
	protected void debug(String message , Throwable t) {
		if(log.isDebugEnabled()) {
			log.debug(message , t);
		}
	}

	/**
	 *
	 * 打印日志信息(包含异常信息)
	 *
	 * @param message
	 *            调试信息
	 * @param t
	 */
	protected void info(String message , Throwable t) {
		if(log.isInfoEnabled()) {
			log.info(message , t);
		}
	}

	/**
	 * 打印错误信息
	 *
	 * @param message
	 *            错误信息
	 */
	protected void error(String message) {
		log.error(message);
	}

	/**
	 * 打印错误信息
	 *
	 * @param message
	 *            错误信息
	 * @param t
	 */
	protected void error(String message , Throwable t) {
		log.error(message , t);
	}

	/**
	 * 设置泛型类
	 *
	 * @param index
	 */
	@SuppressWarnings("unchecked")
	public void setGenericType(int index) {
		Type genType = getClass().getGenericSuperclass();
		Type [] params = ((ParameterizedType)genType).getActualTypeArguments();
		this.cls = (Class<T>)params[index];
	}
	@Override
	public Serializable save(T entity) {
		return super.save(entity);
	}

	@Override
	public boolean jdbcBatchSave(List<T> entitys) throws Exception {
		return super.jdbcBatchSave(entitys);
	}

	@Override
	public boolean batchUpdate(List<T> entitys) throws Exception {
		return super.batchUpdate(entitys);
	}

	@Override
	public boolean batchUpdate(List<T> entitys , boolean isUpdateNullField) throws Exception {
		return super.batchUpdate(entitys , isUpdateNullField);
	}

	@Override
	public boolean batchUpdate(String ... sqls) {
		return super.batchUpdate(sqls);
	}

	@Override
	public boolean batchDelete(Integer [] ids) throws Exception {
		boolean result = false;
		result = deleteByIds(ids , result);
		return result;
	}

	@Override
	public boolean batchDelete(String [] ids) throws Exception {
		boolean result = false;
		result = deleteByIds(ids , result);
		return result;
	}

	@Override
	public void batchDelete(Collection<T> entitys) {
		super.batchDelete(entitys);
	}

	@Override
	public void saveOrUpdate(T entity) {
		super.saveOrUpdate(entity);
	}

	@Override
	public void delete(T entity) {
		super.delete(entity);
	}

	@Override
	public T get(Serializable id) {
		return (T)super.get(cls , id);
	}

	@Override
	public T findUniqueByProperty(String propertyName , Object value) {
		return (T)super.findUniqueByProperty(cls , propertyName , value);
	}

	@Override
	public List<T> findByProperty(String propertyName , Object value) {
		return (List<T>)super.findByProperty(cls , propertyName , value);
	}

	@Override
	public List<T> loadAll() {
		return (List<T>)super.loadAll(cls);
	}

	@Override
	public void deleteEntityById(Serializable id) {
		super.deleteEntityById(cls , id);
	}

	@Override
	public List<T> findByHql(String hql) {
		return super.findByHql(hql);
	}

	@Override
	public int updateBySql(String sql) {
		return super.updateBySql(sql);
	}

	@Override
	public List<T> findListBySql(String sql , Object ... params) throws Exception {
		return super.findListBySql(sql , cls , params);
	}

	@Override
	public List<T> findListBySql(String sql , String [] columnAliases , Object ... params) {
		return (List<T>)super.findListBySql(sql , columnAliases , cls , params);
	}

	@Override
	public List<T> findByPropertyisOrder(String propertyName , Object value , boolean isAsc) {
		return (List<T>)super.findByPropertyisOrder(cls , propertyName , value , isAsc);
	}

	@Override
	public List<T> findByHql(String hql , Object [] params) {
		return super.findByHql(hql , params);
	}

	@Override
	public PageBean pageList(DetachedCriteria dc , int pageNo , int pageSize) {
		return super.pageList(dc , pageNo , pageSize);
	}

	@Override
	public PageBean pageList(String sql , int pageNo , int pageSize) {
		return super.pageList(sql , pageNo , pageSize);
	}

	@Override
	public Session getSession() {
		return super.getSession();
	}

	@Override
	public Map<Object , Object> getHashMapbyHql(String hql) {
		return super.getHashMapbyHql(hql);
	}

	@Override
	public Integer executeSql(String sql , List<Object> params) {
		return super.executeSql(sql , params);
	}

	@Override
	public Integer executeSql(String sql , Object [] params) {
		return super.executeSql(sql , params);
	}

	@Override
	public Integer executeSql(String sql , Map<String , Object> params) {
		return super.executeSql(sql , params);
	}

	@Override
	public Object executeSqlReturnKey(String sql , Map<String , Object> params) {
		return super.executeSqlReturnKey(sql , params);
	}

	@Override
	public List<Map<String , Object>> findForJdbc(String sql , Object [] params) {
		return super.findForJdbc(sql , params);
	}

	@Override
	public Map<String , Object> findOneForJdbc(String sql , Object [] params) {
		return super.findOneForJdbc(sql , params);
	}

	@Override
	public Integer executeHql(String hql) {
		return super.executeHql(hql);
	}

	@Override
	public List<Map<String , Object>> callableStatementByName(String proc , List<SqlParameter> params , Map<String , Object> outParam) {
		return super.callableStatementByName(proc , params , outParam);
	}

	@Override
	public void updateEntitiy(T entity) {
		super.updateEntitiy(entity);
	}

	@Override
	public List<T> executeQuery(String hql , Object [] values) {
		return super.executeQuery(hql , values);
	}

	@Override
	public Map<String , Object> callableStatementByName(String proc , List<SqlParameter> params) {
		return super.callableStatementByName(proc , params);
	}

	@Override
	public int getTableDataCount() {
		return super.getTableDataCount(cls);
	}

	@Override
	public List<T> findByDetached(DetachedCriteria dc) {
		return super.findByDetached(dc);
	}

	@Override
	public List<Serializable> hibernateBatchSave(List<T> entitys) throws Exception {
		return super.hibernateBatchSave(entitys);
	}

	@Override
	public List<T> loadByMultipleId(Class<T> cls , Object [] Ids) {
		return super.loadByMultipleId(cls , Ids);
	}

	@Override
	public List<T> loadByMultipleId(Class<T> cls , List<String> ids) {
		return super.loadByMultipleId(cls , ids);
	}

	private boolean deleteByIds(Object [] ids , boolean result) throws Exception {
		try {
			Field [] declaredFields = cls.getDeclaredFields();
			String idColumnName = null;
			for(Field field : declaredFields) {
				Method method = getMethod(cls , field);
				Id id = getId(method , field);
				if(id != null) {
					Column column = field.getAnnotation(Column.class);
					if(column == null) {
						column = method.getAnnotation(Column.class);
					}
					if(column != null) {
						idColumnName = column.name();
					} else {
						idColumnName = field.getName();
					}
					break;
				}
			}
			if(idColumnName == null) {
				Table table = cls.getAnnotation(Table.class);
				String tableName = table.name();
				throw new Exception("数据表：" + tableName + "未设置主键!");
			}
			DetachedCriteria dc = DetachedCriteria.forClass(cls);
			Criterion in = Restrictions.in(idColumnName , ids);
			dc.add(in);
			List<T> entities = findByDetached(dc);
			if(entities != null) {
				this.batchDelete(entities);
			}
			result = true;
		} catch (Exception e) {
			throw e;
		}
		return result;
	}

	public List<Map<String , Object>> findList(String sql , Object [] params) {
		return super.findForJdbc(sql , params);
	}
}
